package com.quan.common.aop;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.quan.common.annotation.Log;
import com.quan.common.enums.LogType;
import com.quan.common.utils.CommonUtils;
import com.quan.common.utils.IpHelper;
import com.quan.common.utils.JwtTokenUtils;
import com.quan.system.common.amqp.producer.ProducerMessageLogger;
import com.quan.system.entity.SystemLog;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;

@Aspect
@Component
public class LogAspect {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private ProducerMessageLogger loggerMessageProducer;

	/**
	 * JwtToken秘钥
	 */
	@Value("${jwt.secret:123456}")
	private String jwtSecret;

	@Pointcut("@annotation(com.quan.common.annotation.Log)")
	public void annotationController() {
	}

	@Around("annotationController()")
	public Object controllerOperateLog(ProceedingJoinPoint point) throws Throwable {
		Object result = null;
		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();

		Long start = System.currentTimeMillis(), end = 0L, spendTime = 0L;
		result = point.proceed();

		MethodSignature signature = (MethodSignature) point.getSignature();
		// 目标对象
		// String actionClass = point.getTarget().getClass().getName();
		// 目标方法
		// String actionMethod = signature.getName();
		// 参数
		Object[] args = point.getArgs();

		List<Object> list = filterParams(args);

		try {
			String params = JSON.toJSONString(list, SerializerFeature.PrettyFormat);

			// 注解日志
			Log log = signature.getMethod().getAnnotation(Log.class);

			end = System.currentTimeMillis();
			spendTime = end - start;

			if (null != log && log.active()) {
				SystemLog entity = new SystemLog();

				// 非登录日志
				if (!log.type().getName().equals(LogType.LOGIN.getName())) {
					setUserInfo(entity, request, params);
				} else {
					JSONArray array = JSON.parseArray(params);
					JSONObject obj = JSON.parseObject(array.get(0).toString());
					entity.setUserName(obj.getString("username").toString());
				}

				entity.setLogType(log.type().getName());
				entity.setLogDesc(log.desc());
				entity.setRequestMethod(request.getMethod());
				entity.setRequestUri(request.getRequestURI());
				entity.setSpendTime(spendTime.intValue());
				entity.setIp(IpHelper.getIpAddr(request));

				this.loggerMessageProducer.sender(entity);
			}
		} catch (Exception e) {
			logger.error("日志记录异常：{}", e.getMessage());
		}

		return result;
	}

	/**
	 * 操作用户
	 * 
	 * @param entity
	 * @param request
	 * @param params
	 */
	private void setUserInfo(SystemLog entity, HttpServletRequest request, String params) {
		String token = request.getHeader("Auth-Token");
		if (null != token) {
			Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
			if (null != parse) {
				Claims body = parse.getBody();
				entity.setUserId(Long.valueOf(body.get("userId").toString()));
				entity.setUserName(body.get("sub").toString());
				params = CommonUtils.removeAllTrim(params);
				entity.setRequestParams(params.equals("[{}]") ? null : params);
			}
		}
	}

	/**
	 * 过滤参数
	 * 
	 * @param args
	 * @return
	 */
	private List<Object> filterParams(Object[] args) {
		List<Object> list = new ArrayList<Object>();
		for (Object object : args) {
			list.add(object);
		}
		Iterator<Object> iterator = list.iterator();
		while (iterator.hasNext()) {
			Object object = (Object) iterator.next();
			if (object instanceof StandardMultipartHttpServletRequest) {
				iterator.remove();
			}
			if (object instanceof BeanPropertyBindingResult) {
				iterator.remove();
			}
			if (object == null) {
				iterator.remove();
			}
		}
		return list;
	}

}
